//package com.share.tx.util;
//
//import java.lang.reflect.Method;
//import java.util.List;
//
//import javax.annotation.Resource;
//
//import org.aopalliance.intercept.MethodInterceptor;
//import org.aopalliance.intercept.MethodInvocation;
//import org.apache.ibatis.mapping.BoundSql;
//import org.apache.ibatis.mapping.MappedStatement;
//import org.apache.ibatis.session.SqlSessionFactory;
//import org.mybatis.spring.MyBatisSystemException;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.dao.DataAccessException;
//import org.springframework.jdbc.CannotGetJdbcConnectionException;
//
//import com.mchange.v2.resourcepool.CannotAcquireResourceException;
//import com.travelsky.jcf.applog.JcfLogFactory;
//import com.travelsky.jcf.applog.JcfLogger;
//import com.travelsky.pss.ri.util.RiCheckUtils;
//import com.travelsky.pss.ri.util.monitor.MonitorService;
//
///**
// * <p>Title: DasAdvisor </p>
// * <p>Description: sql语句执行时间 返回size通知 </p>
// * /*
// * retry思路：count是proxy类的属性，proxy类只被spring加载一次，存放在spring容器中。所以不管proxy类的方法执行成功还是失败，都要把count重置。
// *          但是当两个线程同时调用proxy类时，因为proxy类及其属性是线程共有的，所以count属性会累记增加。
// *          所以用线程绑定变量ThreadLocal，让count属性成为线程私有的。
// *          单线程中会有多个proxy类，但是这多个proxy类的方法肯定是按顺序执行的。所以每个proxy类的方法不管执行成功还是失败，都要把count重置。
// *          
// *          
// *          经测试：此方式会在切service包时产生死循环
// * 
// */
//public class RI_DasAdvisor implements MethodInterceptor {
//	private static final String SERVICE_NAME="UnifEdbAdvisor";
//	private static final String MESSAGE = 
//			"A ResourcePool could not acquire a resource from its primary factory or source";
//
//	/**
//	 * CAT:日志
//	 */
//	private static final JcfLogger CAT = JcfLogFactory
//			.getJcfLogger(RI_DasAdvisor.class,"shareDas");
//
//	@Resource
//	private SqlSessionFactory sqlSessionFactory;
//
//	@Autowired
//	private DasAdvisorHelper dasAdvisorHelper;
//
//	//sql重复执行次数
//	public static ThreadLocal<Integer> count = new ThreadLocal<Integer>(){
//		//通过匿名内部类覆盖ThreadLocal的InitialValue方法，指定初值
//		protected Integer initialValue() {
//			return 1;
//		};
//	};
//
//	@Override
//	public Object invoke(MethodInvocation invocation) throws Throwable {
//		Object result = null;
//		String flag = getMethodString(invocation);
//		long start = System.currentTimeMillis();
//		try {
//			result = invocation.proceed();
//			StringBuilder sb = new StringBuilder();
//			long time = System.currentTimeMillis() - start;
//			sb.append("Executed " + flag + " [ timeCost -> " + time
//					+ " ms , result(size) -> ");
//			if (result instanceof List) {
//				sb.append(((List<?>) result).size());
//			} else {
//				sb.append(result);
//			}
//			sb.append(" ]");
//			if (time > 1000) {
//				//CAT.error(sb.toString());
//				//超过1000ms打印具体sql
//				logHandler(invocation, sb);
//			} else {
//				CAT.info(sb.toString());
//			}
//			//执行成功，重置
//			count.set(1);
//			return result;
//		}catch(CannotGetJdbcConnectionException e){
//			MonitorService.sendErrorAlarmMessageToTam(SERVICE_NAME, "Could not get JDBC Connection");
//			throw e;
//		}catch(CannotAcquireResourceException e){
//			MonitorService.sendErrorAlarmMessageToTam(SERVICE_NAME, MESSAGE);
//			throw e;
//		}catch (MyBatisSystemException e) {
//			if (count.get() <= dasAdvisorHelper.getRetryTimes()) {
//				Thread.sleep(dasAdvisorHelper.getSleepTime());
//				CAT.error(flag + " 重复执行: " + count.get() + "次，失败");
//				count.set(count.get()+1);
//				return invoke(invocation);
//			}else{
//				CAT.error(flag + " 一共重试: " + dasAdvisorHelper.getRetryTimes() + "次，失败");
//				//执行失败，重置
//				count.set(1);
//				throw e;
//			}
//		}catch (DataAccessException e) {
//			StringBuilder sb = new StringBuilder();
//			sb.append("Executed ").append(flag).append(" [ timeCost -> ");
//			sb.append((System.currentTimeMillis() - start)).append(" ms ] ");
//			sb.append(e.getClass().getName()).append(",");
//			sb.append(e.toString());
//			CAT.error(sb.toString());
//			throw e;
//		}
//	}
//
//	private void logHandler(MethodInvocation invocation, StringBuilder sb) {
//		String name = invocation.getMethod().getDeclaringClass().getName() + "." + invocation.getMethod().getName();
//		if (RiCheckUtils.isNotEmpty(name) && name.contains("Mapper")) {
//			String sql = getMyBatisSql(name, null, sqlSessionFactory);
//			sb.append("超时sql: "+sql);
//			CAT.error(sb.toString());
//		}
//	}
//
//	/**
//	 * getMyBatisSql: 获取sql语句的输出文本
//	 * @param id parameter sqlSessionFactory
//	 * @return sql语句
//	 */
//	private String getMyBatisSql(String id, Object[] parameter,SqlSessionFactory sqlSessionFactory) { 
//		String sql = "";
//		try {
//			MappedStatement ms = sqlSessionFactory.getConfiguration().getMappedStatement(id); 
//			BoundSql boundSql = ms.getBoundSql(parameter);  
//			sql = boundSql.getSql(); 
//		} catch (Exception e) {
//			CAT.error(e.getMessage());
//		}
//		return sql;
//	}
//
//	/**
//	 * GetMethodString: 获取MethodInvocation的输出文本
//	 * @param invocation
//	 * @return 输出文本
//	 */
//	private static String getMethodString(MethodInvocation invocation) {
//		Method method = invocation.getMethod();
//		StringBuffer sb = new StringBuffer();
//		sb.append(method.getDeclaringClass().getSimpleName());
//		sb.append("@[");
//		sb.append(method.getReturnType().getSimpleName()).append(" ");
//		sb.append(method.getName());
//		sb.append("(");
//		@SuppressWarnings("rawtypes")
//		Class[] params = method.getParameterTypes();
//		for (int j = 0; j < params.length; j++) {
//			// 参数是泛型是，无法区分两个方法，后续补充
//			sb.append(params[j].getSimpleName());
//			if (j < (params.length - 1)) {
//				sb.append(",");
//			}
//		}
//		sb.append(")]");
//		return sb.toString();
//	}
//
//}
